<?php
/**
 * （logic）
 */
namespace App\Logic\SsBasic;

use App\Models\Basics\Transport;
use App\Models\Product\ProductSku;
use App\Models\SalesReport\DailyVolume;
use App\Models\Shipping\SSku;
use App\Models\Shipping\SSkuApply;
use App\Models\SsBasic\AreaSku;
use App\Models\SsBasic\AreaSkuEstimate;
use App\Models\Stocking\StockingSetDate;
use App\Models\Stocking\StockingSku;
use Illuminate\Support\Facades\DB;
class InitSS
{
    /**
     * 更新备货提货的周期等基础数据 （dss:basic）
     * 设定：每天运行
     */
    public static function exe(){
        try{
            $setDateArr = [];
            $skuArr = [];
            $pCycle = [];
            $price = [];
            $transportDayArr = [];
            $time = strtotime('-1 days');
            //备货sku
            StockingSku::query()
                ->orderBy('id')
                ->chunk(500, function ($ss) use (&$skuArr,&$pCycle,&$price,&$transportDayArr,&$setDateArr,$time){
                    DB::beginTransaction();
                    foreach ($ss as $_ss){
                        list($areaId,$pSkuId) = explode('_',$_ss->area_psku);
                        $classifyId = ProductSku::getValueById($pSkuId,'classify_id') ?? 0;
                        $_ss->area_id = $areaId;
                        $_ss->psku_id = $pSkuId;
                        $_ss->classify_id = $classifyId;
                        $_ss->save();

                        /**********推荐备货比例 start**********/
                        //系统推荐备货比例(7天)
                        $classifyNum7 = StockingSku::query()->where('area_id',$areaId)->where('classify_id',$classifyId)
                            ->sum('avg7');
                        $_ss->recommend_ratio7 = 0;
                        if (floatval($_ss->avg7) > 0 && floatval($classifyNum7) > 0) {
                            $_ss->recommend_ratio7 = round(floatval($_ss->avg7) / floatval($classifyNum7), 2) ?? 0;
                        }

                        //系统推荐备货比例(30天)
                        $classifyNum30 = StockingSku::query()->where('area_id',$areaId)->where('classify_id',$classifyId)
                            ->sum('avg30');
                        $_ss->recommend_ratio30 = 0;
                        if (floatval($_ss->avg30) > 0 && floatval($classifyNum30) > 0) {
                            $_ss->recommend_ratio30 = round(floatval($_ss->avg30) / floatval($classifyNum30), 2) ?? 0;
                        }
                        /**********推荐备货比例 end**********/

                        if(!array_key_exists($_ss->psku_id,$skuArr)){
                            $skuArr[$_ss->psku_id] = ProductSku::getModelById($_ss->psku_id);
                        }
                        $sku = $skuArr[$_ss->psku_id];
                        if(!array_key_exists($_ss->psku_id,$price)){
                            $price[$_ss->psku_id] = ProductSku::getPuPrice($sku);
                        }
                        if(!array_key_exists($_ss->psku_id,$pCycle)){
                            $pCycle[$_ss->psku_id] = ProductSku::getPuCycle($sku);
                        }
                        if(!array_key_exists($_ss->area_id,$transportDayArr)){
                            $_transportDay = Transport::getTransportDay($_ss->area_id);
                            $transportDayArr[$_ss->area_id] = $_transportDay ?: null;
                        }
                        $transportDay = $transportDayArr[$_ss->area_id];
                        if($transportDay){
                            $airDay = $transportDay->air_day;
                            $seaDay = $transportDay->sea_day;
                        }else{
                            $airDay = 0;
                            $seaDay = 0;
                        }
                        $estimate = AreaSkuEstimate::query()->where('area_psku',$_ss->area_psku)->first();
                        for($i = 0;$i < AreaSkuEstimate::ESTIMATE_NUM - 1;$i++){
                            $num = $estimate->{'estimate_num'.$i} ?? 0; //赋值
                            $_ss->{'estimate_num'.$i} = intval($num);
                        }

                        $_ss->unit_price = $price[$_ss->psku_id];
                        $_ss->purchase_cycle = $pCycle[$_ss->psku_id];
                        $_ss->air_day = $airDay;
                        $_ss->air_available = AreaSku::getAvailable($_ss->purchase_cycle,$airDay);
                        $_ss->air_ship_factor = AreaSku::getShipFactor($airDay);
                        $_ss->air_stock_factor = AreaSku::getStockFactor($_ss->purchase_cycle,$airDay);
                        $_ss->sea_day = $seaDay;
                        $_ss->sea_available = AreaSku::getAvailable($_ss->purchase_cycle,$seaDay);
                        $_ss->sea_ship_factor = AreaSku::getShipFactor($seaDay);
                        $_ss->sea_stock_factor = AreaSku::getStockFactor($_ss->purchase_cycle,$seaDay);
                        $setDateKey = $_ss->area_id.'_'.$sku->classify_id;
                        if(!array_key_exists($setDateKey,$setDateArr)){
                            $setDateArr[$setDateKey] = StockingSetDate::getSetDate($_ss->area_id,$sku->classify_id,$_ss->sea_available);
                        }
                        $_ss->set_date = $setDateArr[$setDateKey];
                        if($_ss->status == 4 || $_ss->status == 3){
                            $approvalTime = strtotime($_ss->approval_date);
                            if($approvalTime <= $time){
                                $_ss->apply_num = null;
                                $_ss->approval_num = null;
                                $_ss->approval_date = null;
                                $_ss->apply_remark = null;
                                $_ss->approval_remark = null;
                                $_ss->status = 1;
                                $_ss->seller_id = null;
                            }
                        }
                        $_ss->save();
                        $_ss->over_stock = StockingSku::getOverStock($_ss);
                        $_ss->over_stock_value = StockingSku::getOverStockValue($_ss->over_stock,$_ss->unit_price);
                        $_ss->save();
                    }
                    DB::commit();
                });
            sleep(5);

            //提货产品
            $shippingDate = SSkuApply::initShippingDate();
            SSku::query()
                ->orderBy('id')
                ->chunk(500, function ($ss) use (&$skuArr,&$pCycle,&$transportDayArr,$shippingDate){
                    DB::beginTransaction();
                    foreach ($ss as $_ss){
                        list($areaId,$pSkuId) = explode('_',$_ss->area_psku);
                        $classifyId = ProductSku::getValueById($pSkuId,'classify_id');
                        $_ss->area_id = $areaId;
                        $_ss->psku_id = $pSkuId;
                        $_ss->classify_id = $classifyId;
                        $_ss->save();

                        if(!array_key_exists($_ss->psku_id,$skuArr)){
                            $skuArr[$_ss->psku_id] = ProductSku::getModelById($_ss->psku_id);
                        }
                        $sku = $skuArr[$_ss->psku_id];
                        if(!array_key_exists($_ss->psku_id,$pCycle)){
                            $pCycle[$_ss->psku_id] = ProductSku::getPuCycle($sku);
                        }
                        if(!array_key_exists($_ss->area_id,$transportDayArr)){
                            $_transportDay = Transport::getTransportDay($_ss->area_id);
                            $transportDayArr[$_ss->area_id] = $_transportDay ?: null;
                        }
                        $transportDay = $transportDayArr[$_ss->area_id];
                        if($transportDay){
                            $airDay = $transportDay->air_day;
                            $seaDay = $transportDay->sea_day;
                        }else{
                            $airDay = 0;
                            $seaDay = 0;
                        }
                        $_ss->purchase_cycle = $pCycle[$_ss->psku_id];
                        $_ss->air_day = $airDay;
                        $_ss->air_factor = AreaSku::getSSkuFactor($_ss->purchase_cycle,$airDay);
                        $_ss->sea_day = $seaDay;
                        $_ss->sea_factor = AreaSku::getSSkuFactor($_ss->purchase_cycle,$seaDay);
                        $_ss->save();

                        //提货产品申请
                        foreach($shippingDate as $date => $label){
                            $count = SSkuApply::query()
                                ->where('area_id',$_ss->area_id)
                                ->where('psku_id',$_ss->psku_id)
                                ->where('shipping_date',$date)
                                ->count();
                            if($count == 0){
                                SSkuApply::query()->create(
                                    [
                                        'area_id' => $_ss->area_id,
                                        'psku_id' => $_ss->psku_id,
                                        'shipping_date' => $date
                                    ]);
                            }
                        }
                    }
                    DB::commit();
                });
        }catch (\Exception $e){
            DB::rollBack();
            report($e);
        }
    }
}
